package com.kk.demo.unsface.two.create;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.kk.util.IOutils;

import sun.misc.Unsafe;

public class UnsafeCreateObject {

    /**
     * 获取Unsafe对象
    * 方法描述
    * @return
    * @创建日期 2016年11月18日
    */
    @SuppressWarnings("restriction")
    public static Unsafe getUnsafe() {
        Unsafe safe = null;

        Field fied = null;
        try {
            fied = Unsafe.class.getDeclaredField("theUnsafe");
            fied.setAccessible(true);
            safe = (Unsafe) fied.get(null);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return safe;
    }

    public static void main(String[] args) {
        UnsafeCreateObject unsafeCreate = new UnsafeCreateObject();
        // 快速创建对象
        // unsafeCreate.quickCreateObject();
        // 动态创建对象
       // unsafeCreate.unsafedynnamic(false);
        //破解代码调用
        unsafeCreate.guardCodeInvoke();
        
    }

    /**
     * 快速创建对象的方法
     * 由于unsafe是直接复杂的字节码的内存结构，所以，所有的对象都未初始化（包括属性设置的值），
     * 快速创建对象后，需要自己构造对象的值信息
    * 方法描述
    * @创建日期 2016年11月25日
    */
    public void quickCreateObject() {
        // 首先使用new创建对象，调用a方法
        long startTime = System.nanoTime();
        A newa = new A();
        long newAReturn = newa.a();
        long end = System.nanoTime();
        System.out.println("newobj时间:" + (end - startTime));
        // 使用unSafe来创建对象

        Unsafe unsafe = getUnsafe();
        long unsafeAReturn = -1;
        try {
            long startTimeUnsafe = System.nanoTime();
            A unsafA = (A) unsafe.allocateInstance(A.class);
            // 未经构造函数，快速创建对象,所以，取出来的数据是未经构造初始化的
            // 此使用直接复杂的内存结构，非在堆上创建，效率非常的高
            unsafeAReturn = unsafA.a();
            long endTimeUnsafe = System.nanoTime();
            System.out.println("unsafe时间:" + (endTimeUnsafe - startTimeUnsafe));
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("结果newobj：" + newAReturn);
        System.out.println("结果unsafe：" + unsafeAReturn);
    }

    /**
     * 动态创建对象
    * 方法描述
    * @创建日期 2016年11月25日
    */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void unsafedynnamic(boolean mustBeBootstrap) {
        // 获取unsafe对象
        Unsafe unsafe = getUnsafe();

        String path = UnsafeCreateObject.class.getClassLoader()
                .getResource("com/kk/demo/unsface/two/create/A.class")
                .getPath();
        // 1,读取字节码文件
        File classFile = new File(path);
        FileInputStream input = null;
        try {
            input = new FileInputStream(classFile);
            byte[] context = new byte[(int) classFile.length()];
            input.read(context);
            // 进行定义
            Class unsafeClass = unsafe.defineClass(null, context, 0,
                    context.length, null, null);
            Object value = unsafeClass.getMethod("a")
                    .invoke(unsafeClass.newInstance(), new Object[0]);
            System.out.println("value:" + value);

            // 使用反射直接获取class调用
            Method amethod = A.class.getMethod("a");
            Object invoke = value = amethod.invoke(A.class.newInstance(), new Object[0]);
            System.out.println("进行invoke:" + invoke);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            IOutils.closeStream(input);
        }
    }
    
    
    /**
     * 通过unsafe进行设置私有属性的值
    * 方法描述
    * @创建日期 2016年11月25日
    */
    public void guardCodeInvoke()
    {
        Guard guard = new Guard();
        // 获取unsafe对象
        Unsafe unsafe = getUnsafe();
        
        //获取属性
        try {
            Field accessField = guard.getClass().getDeclaredField("ACCESS_ALLLOWED");
            unsafe.putInt(guard, unsafe.objectFieldOffset(accessField),42);
            //调用结果 
            boolean check = guard.giveAccess();
            
            System.out.println("结果:"+check);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
}
